﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ReadR41;
using Dimeng.ArdisPostProcessor.HomagLC4Adsn.Ardis;

namespace Dimeng.ArdisPostProcessor.HomagLC4.Ardis
{
    public class R41Helper
    {
        public static R41Data AnalysisR41(string r41path)
        {
            Functions ft = new Functions();
            try
            {
                R41Data data = new R41Data(new System.IO.FileInfo(r41path).Name);

                string r41string = ft.ReadR41ToString(r41path);
                data.ParameterList = ft.MakeParameterList(r41string);
                data.Parts = ft.MakeParts(r41string);
                data.Materials = ft.MakeMaterials(r41string);
                data.Patterns = ft.MakePatterns(r41string);
                data.Sheets = ft.MakeSheets(r41string);
                data.Cuts = ft.MakeCuts(r41string);
                data.Analysis();

                GetPatternTrimsAndMaterials(data);

                data.Parts.ForEach(it => it.PartQtyDone = it.PartQty);

                BlockOptimizer.Optimize(data);
                //OptimizeCutResult(data);

                AnalysisFullCuts(data);

                return data;
            }
            catch (Exception e)
            {
                throw new Exception("读取R41失败，请检查R41文件是否符合Ardis规范", e);
            }
            finally
            {
                ft = null;
            }
        }
        public static void GetPatternTrimsAndMaterials(R41Data data)
        {
            foreach (Pattern p in data.Patterns)
            {
                var sheet = data.Sheets.Find(it => it.SheetNo == p.PatternSheetNumber);

                if (sheet == null)
                    throw new Exception("未找到符合的Sheet数据");

                p.PatternTopTrim = sheet.SheetTrimMinUpper;
                p.PatternRightTrim = sheet.SheetTrimMinRight;
                p.PatternLeftTrim = sheet.SheetTrimMinLeft;
                p.PatternBottomTrim = sheet.SheetTrimMinBottom;
                p.PatternMaterial = data.Materials.Find(it => it.MaterialNo == sheet.SheetMatNo).MaterialName;
                p.PatternThickness = sheet.SheetThick;
            }
        }
        public static void AnalysisFullCuts(R41Data data)
        {
            foreach (Pattern pattern in data.Patterns)
            {
                int cutlevel = 1;
                int Counter = 1;
                //取出第一层的cut
                var cuts = data.Cuts
                               .Where(c => c.CutPatternNo == pattern.PatternNumber
                                           && c.CutLevel == cutlevel)
                               //.OrderBy(c => c.CutNo)
                               .ToList();

                double Length = pattern.PatternL;
                double Width = pattern.PatternW;

                GetChildFullCuts(data, ref Counter, cuts, Length, Width, pattern);
            }
        }

        private static void GetChildFullCuts(R41Data data
                                            , ref int Counter
                                            , List<Cut> cuts
                                            , double length
                                            , double width
                                            , Pattern pattern)
        {
            double StripLength = length;
            double StripWidth = width;
            foreach (Cut c in cuts)
            {
                //把所有CutQty>1的都拆掉，拆成一个一个
                for (int i = 0; i < c.CutQty; i++)
                {
                    #region 判断是否有TrimCut
                    //如果是第1级，而且是第一刀的，则要加上修边信息
                    //左和上修边都要大于0，否则不加修边
                    if (c.CutLevel == 1 && cuts.IndexOf(c) == 0 && i == 0 && pattern.PatternLeftTrim > 0 && pattern.PatternTopTrim > 0)
                    {
                        ExternCut TrimCut = new ExternCut(c);
                        TrimCut.Counter = Counter;
                        Counter++;
                        TrimCut.CutType = CutType.Trim;
                        data.FullCuts.Add(TrimCut);
                        if (c.CutD == 'H')
                        {
                            length = length - pattern.PatternLeftTrim;
                            TrimCut.CutW = pattern.PatternLeftTrim;
                        }
                        else
                        {
                            width = width - pattern.PatternTopTrim;
                            TrimCut.CutW = pattern.PatternTopTrim;
                        }

                        ExternCut TrimSawCut = new ExternCut(c);
                        TrimSawCut.Counter = Counter;
                        Counter++;
                        TrimSawCut.CutType = CutType.SawCut;
                        TrimSawCut.IsTrimSawCut = true;
                        TrimSawCut.CutW = c.Kerf;
                        data.FullCuts.Add(TrimSawCut);
                    }

                    //如果是第2级，而且是第一刀的，则要加上修边信息
                    if (c.CutLevel == 2 && cuts.IndexOf(c) == 0 && i == 0 && pattern.PatternLeftTrim > 0 && pattern.PatternTopTrim > 0)
                    {
                        ExternCut TrimCut = new ExternCut(c);
                        TrimCut.Counter = Counter;
                        Counter++;
                        TrimCut.CutType = CutType.Trim;
                        data.FullCuts.Add(TrimCut);
                        if (c.CutD == 'H')
                        {
                            length = length - pattern.PatternLeftTrim;
                            TrimCut.CutW = pattern.PatternLeftTrim;
                        }
                        else
                        {
                            width = width - pattern.PatternTopTrim;
                            TrimCut.CutW = pattern.PatternTopTrim;
                        }

                        ExternCut TrimSawCut = new ExternCut(c);
                        TrimSawCut.Counter = Counter;
                        Counter++;
                        TrimSawCut.CutType = CutType.SawCut;
                        TrimSawCut.IsTrimSawCut = true;
                        TrimSawCut.CutW = c.Kerf;
                        data.FullCuts.Add(TrimSawCut);
                    }
                    #endregion

                    //直接复制于原始的Cut
                    ExternCut ExtCut = new ExternCut(c, true);
                    ExtCut.Counter = Counter;
                    data.FullCuts.Add(ExtCut);
                    Counter++;

                    ////如果是板件，就找一下板件的信息
                    //if (ExtCut.CutType == CutType.Part)
                    //{
                    //    FillPartList(ExtCut, data.Parts, pattern.PatternQty);
                    //}

                    ExternCut SawCut = new ExternCut(c);
                    SawCut.CutType = CutType.SawCut;
                    SawCut.Counter = Counter;
                    SawCut.CutW = c.Kerf;
                    data.FullCuts.Add(SawCut);

                    if (c.CutD == 'H')
                    {
                        length = length - c.CutW - c.Kerf;
                    }
                    else
                    {
                        width = width - c.CutW - c.Kerf;
                    }
                }

                if (c.CutPartNo == 0)
                {
                    var childcuts = data.Cuts.Where(it => it.CutParentNo == c.CutNo).ToList();
                    double stripLength = 0;
                    double stripWidth = 0;
                    if (c.CutD == 'H')
                    {
                        stripLength = c.CutW;
                        stripWidth = StripWidth;
                    }
                    else
                    {
                        stripLength = StripLength;
                        stripWidth = c.CutW;
                    }

                    GetChildFullCuts(data, ref Counter, childcuts, stripLength, stripWidth, pattern);
                }

                //如果是最后一个的话,需要考虑剩余空间的大小，再决定是否加入余料的信息
                if (cuts.IndexOf(c) == (cuts.Count() - 1))
                {
                    //ExternCut LastSawCut = new ExternCut(c);
                    //LastSawCut.Counter = Counter;
                    //Counter++;
                    //LastSawCut.CutType = CutType.SawCut;
                    //LastSawCut.CutW = c.Kerf;
                    //LastSawCut.Kerf = c.Kerf;
                    //data.FullCuts.Add(LastSawCut);

                    double RestVolumn;
                    if (c.CutD == 'H')
                        RestVolumn = length + c.Kerf;
                    else RestVolumn = width + c.Kerf;

                    //2017.8.4注释了对小于30的空间的处理，因为需要这个数据不能忽略
                    ////如果剩下空间太小就直接
                    //if (RestVolumn < 30)
                    //    return;

                    //2017.8.7 对余量小于等于0的时候，则不作为余料
                    if (RestVolumn <= 0)
                    {
                        return;
                    }

                    ExternCut LastCut = new ExternCut(c);
                    LastCut.Counter = Counter;
                    LastCut.CutType = CutType.Rest;
                    LastCut.CutW = RestVolumn;
                    data.FullCuts.Add(LastCut);
                    Counter++;
                }
            }
        }

        /// <summary>
        /// 因为新加入了两个cut，所以要把原来的子cut的level都加2
        /// </summary>
        /// <param name="data"></param>
        /// <param name="cut"></param>
        private static void changeChildrenCutLevel(R41Data data, Cut cut)
        {
            if (cut.CutPartNo == 0)
            {
                data.Cuts
                        .Where(it => it.CutParentNo == cut.CutNo)
                        .ToList()
                        .ForEach(it =>
                        {
                            it.CutLevel += 2;
                            changeChildrenCutLevel(data, it);
                        });
            }
        }       

        public static Part CopyPart(int Qty, Part p)
        {
            Part NewPart = new Part();
            NewPart.PartQty = Qty;
            NewPart.PartCalc = p.PartCalc;
            NewPart.PartD = p.PartD;
            NewPart.PartDrawing = p.PartDrawing;
            NewPart.PartFigDef = p.PartFigDef;
            NewPart.PartFigID = p.PartFigID;
            NewPart.PartFigParam = p.PartFigParam;
            NewPart.PartFigPartID = p.PartFigPartID;
            NewPart.PartFNo = p.PartFNo;
            NewPart.PartL = p.PartL;
            NewPart.PartLowPriQty = p.PartLowPriQty;
            NewPart.PartMatNo = p.PartMatNo;
            NewPart.PartNo = p.PartNo;
            NewPart.PartPri = p.PartPri;
            NewPart.PartProd = p.PartProd;
            NewPart.PartRef = p.PartRef;
            NewPart.PartRemark = p.PartRemark;
            NewPart.PartRemark2 = p.PartRemark2;
            NewPart.PartRemark3 = p.PartRemark3;
            NewPart.PartTwinNo = p.PartTwinNo;
            NewPart.PartW = p.PartW;
            return NewPart;
        }
    }
}
